package com.share.common.redis.configure;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * redis配置
 */
@Configuration
@EnableCaching
@AutoConfigureBefore(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport {
    // 定义默认字符集（避免中文乱码）
    private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

    /**
     * 1. 自定义 FastJSON 2 Redis 序列化器（解决 FastJson2JsonRedisSerializer 未定义问题）
     */
    public static class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
        private final Class<T> clazz;

        public FastJson2JsonRedisSerializer(Class<T> clazz) {
            this.clazz = clazz;
        }

        @Override
        public byte[] serialize(T t) {
            if (t == null) {
                return new byte[0]; // 空对象返回空字节数组，避免 null 异常
            }
            // 使用 FastJSON 2 序列化，配置 WriteClassName 以支持反序列化时识别泛型
            return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
        }

        @Override
        public T deserialize(byte[] bytes) {
            if (bytes == null || bytes.length == 0) {
                return null; // 空字节数组返回 null
            }
            // 使用 FastJSON 2 反序列化，配置 SupportAutoType 以支持自动类型识别（避免类型转换异常）
            return JSON.parseObject(new String(bytes, DEFAULT_CHARSET), clazz,
                    JSONReader.Feature.SupportAutoType, // 关键：支持反序列化时自动识别对象类型
                    JSONReader.Feature.IgnoreAutoTypeNotMatch); // 忽略类型不匹配的情况（提高兼容性）
        }
    }

    /**
     * 2. 定义 RedisTemplate<String, Object>（解决泛型不匹配问题，与 Handler 依赖一致）
     */
    @Bean
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        FastJson2JsonRedisSerializer jsonSerializer = new FastJson2JsonRedisSerializer<>(Object.class);

        // -------------------------- Key 序列化配置 --------------------------
        // Key 使用 String 序列化（避免乱码，Redis 控制台查看 Key 更直观）
        StringRedisSerializer stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer);
        template.setHashKeySerializer(stringSerializer); // Hash 的 Key 也用 String 序列化

        // -------------------------- Value 序列化配置 --------------------------
        // Value 使用 FastJSON 2 序列化（支持复杂对象，性能优于默认 JDK 序列化）
        template.setValueSerializer(jsonSerializer);
        template.setHashValueSerializer(jsonSerializer); // Hash 的 Value 也用 FastJSON 2 序列化

        // 初始化模板
        template.afterPropertiesSet();
        return template;
    }
}
